package com.danbay.cloud.device.service.electricmeter;

import com.danbay.cloud.base.constants.DeviceType;
import com.danbay.cloud.base.device.DeviceHelper;
import com.danbay.cloud.device.api.dto.DeviceLoginDto;
import com.danbay.cloud.device.api.dto.DeviceLogoutDto;
import com.danbay.cloud.device.api.dto.DevicePositionDto;
import com.danbay.cloud.device.api.dto.DeviceRegDto;
import com.danbay.cloud.device.api.dto.electricmeter.*;
import com.danbay.cloud.device.api.service.IDevicePositionService;
import com.danbay.cloud.device.api.service.electricmeter.IEmConsumptionService;
import com.danbay.cloud.device.api.service.electricmeter.IEmService;
import com.danbay.cloud.device.entity.electricmeter.EmFeeGroup;
import com.danbay.cloud.device.entity.electricmeter.EmInfo;
import com.danbay.cloud.device.mapper.electricmeter.EmFeeGroupMapper;
import com.danbay.cloud.device.mapper.electricmeter.EmInfoMapper;
import com.danbay.cloud.device.mapper.electricmeter.EmMapper;
import com.danbay.framework.exception.BusinessException;
import com.danbay.framework.utils.BeanValidator;
import com.danbay.framework.utils.DateUtils;
import com.danbay.framework.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;

@Slf4j
@Service
public class EmService implements IEmService {

    @Autowired
    private EmMapper emMapper;

    @Autowired
    private EmInfoMapper emInfoMapper;

    @Autowired
    private EmFeeGroupMapper emFeeGroupMapper;

    @Autowired
    private IEmConsumptionService emConsumptionService;

    @Autowired
    private IDevicePositionService devicePositionService;

    @Override
    public String register(DeviceRegDto regDto) throws BusinessException {
        //验证参数
        BeanValidator.valid(regDto);
        String deviceId = "";
        String controlId = regDto.getFatherDevId();
        String mac = regDto.getMac();
        if (StringUtils.isBlank(controlId)) {
            throw new BusinessException("设备所属父级设备ID为空");
        }
        //TODO 查询中控看是否存在
        boolean controlExist = true;
        if (!controlExist) {
            throw new BusinessException("未找到该设备:" + mac + "，关联的中控:" + controlId);
        }
        EmInfo emInfo = emMapper.getEmInfoByMac(mac);
        if (null == emInfo) {
            deviceId = addElectricInfo(regDto);
        } else {
            deviceId = emInfo.getDeviceId();
            //是否要换中控
            if (!controlId.equals(emInfo.getControlId())) {
                EmInfo modifyElectricmeterInfo = EmInfo.builder()
                        .deviceId(deviceId)
                        .controlId(controlId)
                        .build();
                modifyElectricmeterInfoById(modifyElectricmeterInfo);
                //记录迁移日志
                log.warn("设备发生迁移,设备:{}从中控:{}迁移到中控:{}", deviceId, emInfo.getControlId(), controlId);
            }
        }
        return deviceId;
    }

    @Override
    public int login(DeviceLoginDto loginDto) {
        EmInfo modifyElectricmeterInfo = EmInfo.builder()
                .deviceId(loginDto.getDevId())
                .controlId(loginDto.getOwner())
                .status(1)
                .build();
        return modifyElectricmeterInfoById(modifyElectricmeterInfo);
    }

    @Override
    public int logout(DeviceLogoutDto logoutDto) {
        EmInfo modifyElectricmeterInfo = EmInfo.builder()
                .deviceId(logoutDto.getDevId())
                .status(0)
                .build();
        return modifyElectricmeterInfoById(modifyElectricmeterInfo);
    }

    @Override
    public EmInfoBaseDto information(String deviceId) throws BusinessException {
        //TODO 先从缓存取数据
        EmInfo electricmeterInfo = selectById(deviceId);
        if (null == electricmeterInfo) {
            throw new BusinessException("未找到该电表设备:" + deviceId);
        }
        //是否开始计费
        EmFeeGroup electricmeterFeeGroup
                = EmFeeGroup.builder().deviceId(deviceId).del(0).build();
        EmFeeGroup efg = emFeeGroupMapper.selectOne(electricmeterFeeGroup);
        int chargeStatus = 0;
        if (null != efg) {
            chargeStatus = 1;
        }

        Date date = new Date();
        EmConsumptionBetweenDto consumptionQueryDto = new EmConsumptionBetweenDto();
        consumptionQueryDto.setDeviceId(deviceId);
        //本月冻结
        consumptionQueryDto.setBeginTime(Long.parseLong(DateFormatUtils.format(DateUtils.getBeginTimeOfMonth(date),
                DateUtils.YMDHMS2)));
        consumptionQueryDto.setEndTime(Long.parseLong(DateFormatUtils.format(date, DateUtils.YMDHMS2)));
        Double monthFreeze = emConsumptionService.getConsumptionBetween(consumptionQueryDto);

        //昨日冻结
        consumptionQueryDto.setBeginTime(Long.parseLong(DateFormatUtils.format(DateUtils.getYesterdayBeginTime(),
                DateUtils.YMDHMS2)));
        consumptionQueryDto.setEndTime(Long.parseLong(DateFormatUtils.format(DateUtils.getYesterdayFinalTime(),
                DateUtils
                        .YMDHMS2)));
        Double yesterdayFreeze = emConsumptionService.getConsumptionBetween(consumptionQueryDto);
        EmInfoBaseDto eid = new EmInfoBaseDto(deviceId, electricmeterInfo.getStatus(),
                electricmeterInfo.getMeterCount(), monthFreeze, yesterdayFreeze, chargeStatus);
        //TODO 做缓存
        return eid;
    }

    @Override
    public EmInfoDetailDto detail(String deviceId) throws BusinessException {

        EmInfo electricmeterInfo = selectById(deviceId);
        if (null == electricmeterInfo) {
            throw new BusinessException("未找到该电表设备:" + deviceId);
        }

        DevicePositionDto deviceDosition = devicePositionService.getPositionByDeviceId(deviceId);

        EmInfoDetailDto detailDto = EmInfoDetailDto.builder()
                .deviceId(deviceId)
                .controlId(electricmeterInfo.getControlId())
                .mac(electricmeterInfo.getMac())
                .meterCount(electricmeterInfo.getMeterCount())
                .status(electricmeterInfo.getStatus())
                .name(electricmeterInfo.getName())
                .phoneNum(deviceDosition.getPhoneNum())
                .address(deviceDosition.getAddress())
                .contractNum(deviceDosition.getContractNum())
                .build();
        return detailDto;
    }

    @Override
    public EmConsumptionDto consumption(EmConsumptionQueryDto queryDto) throws BusinessException {
        BeanValidator.valid(queryDto);
        EmConsumptionDto consumptionDto = null;
        long beginTime = 0;
        long endTime = 0;
        Date date = DateUtils.parseDate(queryDto.getDate());
        if (1 == queryDto.getType()) {
            beginTime = Long.parseLong(DateFormatUtils.format(DateUtils.getBeginTimeOfDay(date), DateUtils.YMDHMS2));
            endTime = Long.parseLong(DateFormatUtils.format(DateUtils.getEndTimeOfDay(date), DateUtils.YMDHMS2));
        } else if (2 == queryDto.getType()) {
            beginTime = Long.parseLong(DateFormatUtils.format(DateUtils.getBeginTimeOfMonth(date), DateUtils.YMDHMS2));
            endTime = Long.parseLong(DateFormatUtils.format(DateUtils.getEndTimeOfMonth(date), DateUtils.YMDHMS2));
        } else if (3 == queryDto.getType()) {
            beginTime = Long.parseLong(DateFormatUtils.format(DateUtils.getBeginTimeOfYear(date), DateUtils.YMDHMS2));
            endTime = Long.parseLong(DateFormatUtils.format(DateUtils.getEndTimeOfYear(date), DateUtils.YMDHMS2));
        }
        EmConsumptionBetweenDto consumptionQueryDto
                = EmConsumptionBetweenDto.builder()
                .deviceId(queryDto.getDeviceId())
                .type(queryDto.getType())
                .beginTime(beginTime)
                .endTime(endTime)
                .build();
        return emConsumptionService.getConsumption(consumptionQueryDto);
    }

    /**
     * 电表信息入库
     *
     * @param regDto
     * @return
     */
    private String addElectricInfo(DeviceRegDto regDto) {
        //TODO 电表所属房间ID
        String houseInfoId = "";
        //TODO 采集器ID
        String collectorId = "";
        String deviceId = DeviceHelper.generateDeviceId(regDto.getMac(), DeviceType.EM_METER);
        EmInfo electricmeterInfo = EmInfo.builder().addTime(new Date())
                .controlId(regDto.getFatherDevId())
                .collectorId(collectorId)
                .del(0)
                .deviceId(deviceId)
                .houseInfoId(houseInfoId)
                .mac(regDto.getMac())
                .meterCount(0D)
                .name(regDto.getSn())
                .status(1)
                .version(regDto.getVer())
                .switchStatus(0).build();
        emMapper.insertEmInfo(electricmeterInfo);
        return deviceId;
    }

    /**
     * 根据deviceId修改电表信息
     *
     * @param modifyElectricmeterInfo
     * @return
     */
    private int modifyElectricmeterInfoById(EmInfo modifyElectricmeterInfo) {
        //TODO 缓存处理
        return emMapper.modifyEmInfoById(modifyElectricmeterInfo);
    }

    /**
     * 根据ID获取电表信息
     * @param deviceId
     * @return
     */
    private EmInfo selectById(String deviceId) {
        //TODO 缓存
        return emInfoMapper.selectById(deviceId);
    }
}
